package cn.aws360.boot.extend.sms.biz.service.impl;

import cn.aws360.boot.auth.api.LoginApi;
import cn.aws360.boot.base.api.exception.ServiceException;
import cn.aws360.boot.extend.sms.api.SmsSenderApi;
import cn.aws360.boot.extend.sms.api.constant.SmsConstant;
import cn.aws360.boot.extend.sms.api.exception.SmsExceptionEnum;
import cn.aws360.boot.extend.sms.api.pojo.request.SmsLoginCaptchaQuery;
import cn.aws360.boot.extend.sms.biz.service.SmsService;
import cn.aws360.boot.system.biz.service.SysConfService;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static cn.aws360.boot.auth.api.constant.AuthConstant.CACHE_CAPTCHA_EXPIRE;
import static cn.aws360.boot.auth.api.constant.AuthConstant.CACHE_MOBILE_CODE;

/**
 * @author junnan
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SmsServiceImpl implements SmsService {

    private final LoginApi loginApi;
    private final SmsSenderApi smsSenderApi;
    private final SysConfService confService;
    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public Boolean sendLoginCaptcha(SmsLoginCaptchaQuery loginCaptchaQuery) {
        loginApi.checkCaptcha(loginCaptchaQuery.getUuid(), loginCaptchaQuery.getCaptcha());

        String mobile = loginCaptchaQuery.getMobile();
        checkMobile(mobile);

        String smsCode = RandomUtil.randomNumbers(6);
        stringRedisTemplate.opsForValue().set(CACHE_MOBILE_CODE + mobile, smsCode, CACHE_CAPTCHA_EXPIRE, TimeUnit.MINUTES);

        Map<String, Object> paramMap = new HashMap<>(4);
        paramMap.put("code", smsCode);
        paramMap.put("expire", CACHE_CAPTCHA_EXPIRE);

        String sign = confService.getValueByCode(SmsConstant.CONF_SMS_SIGN);
        String tplId = confService.getValueByCode(SmsConstant.CONF_SMS_LOGIN_TPL);
        checkSmsConfig(sign, tplId);
        return smsSenderApi.sendSms(sign, tplId, mobile, paramMap);
    }

    private void checkMobile(String mobile) {
        if (StrUtil.isBlank(mobile)) {
            throw new ServiceException(SmsExceptionEnum.SMS_NOT_SEND_FOR_BLANK);
        }

        String smsCode = stringRedisTemplate.opsForValue().get(CACHE_MOBILE_CODE + mobile);
        if (StrUtil.isNotBlank(smsCode)) {
            throw new ServiceException(SmsExceptionEnum.SMS_NOT_SEND_FOR_EXPIRE);
        }
    }

    private void checkSmsConfig(String sign, String tplId) {
        if (!StrUtil.isAllNotBlank(sign, tplId)) {
            throw new ServiceException(SmsExceptionEnum.SMS_NOT_SEND_FOR_CONFIG_ERROR);
        }
    }

}
